/*
                             *******************
******************************* C SOURCE FILE *******************************
**                           *******************                           **
**                                                                         **
** project		: General Template                                         **
** filename		: COND.C                                                   **
** version		: 1.0                                                      **
** date			: December 31, 1986                                        **
**                                                                         **
*****************************************************************************
**                                                                         **
** Copyright (c) 2011, $pynarak                                            **
** All rights reserved.                                                    **
**                                                                         **
*****************************************************************************

VERSION HISTORY:
----------------

Version			: 1.0
Date 			: December 31, 1986
Revised by 		: $pynarak
Compiler        : GNU GCC
Description 	: Original version.
*/

#define _COND_C_SRC

/****************************************************************************/
/**                                                                        **/
/** MODULES USED                                                           **/
/**                                                                        **/
/****************************************************************************/

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>

/****************************************************************************/
/**                                                                        **/
/** DEFINITIONS AND MACROS                                                 **/
/**                                                                        **/
/****************************************************************************/

#define COUNT_DONE  		10
#define COUNT_HALT1  		3
#define COUNT_HALT2  		6

/****************************************************************************/
/**                                                                        **/
/** TYPEDEFS AND STRUCTURES                                                **/
/**                                                                        **/
/****************************************************************************/

/****************************************************************************/
/**                                                                        **/
/** PROTOTYPES OF LOCAL FUNCTIONS                                          **/
/**                                                                        **/
/****************************************************************************/

void *threadA(void *thread_argv);
void *threadB(void *thread_argv);

/****************************************************************************/
/**                                                                        **/
/** EXPORTED VARIABLES                                                     **/
/**                                                                        **/
/****************************************************************************/

/****************************************************************************/
/**                                                                        **/
/** GLOBAL VARIABLES                                                       **/
/**                                                                        **/
/****************************************************************************/

pthread_mutex_t mutexCNT  = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t mutexCOND = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t  condVAR   = PTHREAD_COND_INITIALIZER;
pthread_t thread1, thread2;

volatile int	counter = 0;

/****************************************************************************/
/**                                                                        **/
/** EXPORTED FUNCTIONS                                                     **/
/**                                                                        **/
/****************************************************************************/

/****************************************************************************/
/**                                                                        **/
/** LOCAL FUNCTIONS                                                        **/
/**                                                                        **/
/****************************************************************************/

int main (int argc, char *argv[])
{
	pthread_create(&thread1, NULL, &threadA, NULL);
	pthread_create(&thread2, NULL, &threadB, NULL);
	pthread_join(thread1, NULL);
	pthread_join(thread2, NULL);

	return 0;
}

void *threadA(void *thread_argv)
{
	while (1)
	{
		pthread_mutex_lock(&mutexCOND);
		while (counter >= COUNT_HALT1 && counter <= COUNT_HALT2)
		{
			pthread_cond_wait(&condVAR, &mutexCOND);
		}
		pthread_mutex_unlock(&mutexCOND);

		pthread_mutex_lock(&mutexCNT);
		counter++;
		printf("Counter value thread A: %d\n",counter);
		pthread_mutex_unlock(&mutexCNT);

		if(counter >= COUNT_DONE) return(NULL);
	}
}

void *threadB(void *thread_argv)
{
    for(;;)
    {
		pthread_mutex_lock(&mutexCOND);
		if (counter < COUNT_HALT1 || counter > COUNT_HALT2)
		{
			pthread_cond_signal(&condVAR);
		}
		pthread_mutex_unlock(&mutexCOND);

		pthread_mutex_lock(&mutexCNT);
		counter++;
		printf("Counter value thread B: %d\n", counter);
		pthread_mutex_unlock(&mutexCNT);

		if(counter >= COUNT_DONE) return(NULL);
    }
}

/****************************************************************************/
/**                                                                        **/
/** EOF                                                                    **/
/**                                                                        **/
/****************************************************************************/
